// utils/notificationService.js
import Stomp from 'stompjs';
import store from '@/store'; // 确保路径相对于您项目的 store
import { showAppPush } from '@/components/APPPush/index.js'; // 确保路径相对于您项目的插件
// 引入统一配置文件
import config from '@/config/index.js';
const WS_BASE_URL = config.websocketURL; // 您的 WebSocket 服务端点

let stompClient = null;
let currentUserId = null;
let currentUserToken = null;
let socketTask = null; // 保存 uni.connectSocket 返回的 SocketTask 实例

let reconnectAttempts = 0;
const MAX_RECONNECT_ATTEMPTS = 5;
const RECONNECT_DELAY = 5000; // ms

function log(message, type = 'info', data = null) {
    const prefix = `[通知服务] [${new Date().toLocaleTimeString()}]`;
    const fullMessage = `${prefix} ${message}`;
    
    if (data) {
        console[type === 'error' ? 'error' : (type === 'warn' ? 'warn' : 'log')](fullMessage, data);
    } else {
        console[type === 'error' ? 'error' : (type === 'warn' ? 'warn' : 'log')](fullMessage);
    }
    
    // UI Toast for errors (optional, can be noisy)
    // if (type === 'error' && !message.toLowerCase().includes("连接错误") && !message.toLowerCase().includes("stomp 连接失败")) {
    //     uni.showToast({ title: `通知服务: ${message.substring(0, 30)}...`, icon: 'none', duration: 3500 });
    // }
}

function handleNotificationDisplay(notificationData) {
    log('准备显示应用内推送通知', 'info', notificationData);

    let modalTitle = '新通知';
    let modalContent = '您有一条新消息，请查看。';
    let modalType = 'REPLY_COMMENT'; // 默认
    let targetUserName = null;       
    let targetNickName = null;
    let avatar = ''; // 默认头像

    if (notificationData) {
        modalTitle = notificationData.title || (notificationData.notificationType === 'NEW_CHAT_MESSAGE' ? (notificationData.senderNickname || '新消息') : modalTitle);
        modalContent = notificationData.contentPreview || notificationData.content || modalContent;
        
        if (notificationData.notificationType === 'NEW_CHAT_MESSAGE') {
            modalType = 'OPEN_CHAT';
            targetUserName = notificationData.senderId; 
            targetNickName = notificationData.senderNickname || '对方';
            avatar = notificationData.senderAvatar || avatar;
        } else if (notificationData.notificationType === 'POST_REPLY' || notificationData.notificationType === 'REPLY_COMMENT') {
            modalType = 'REPLY_COMMENT';
        }
        // ... 其他通知类型 ...
    }

    const params = {
        inApp: true, voice: true, vibration: true,
        userName: targetUserName, 
        nickName: targetNickName, 
        messageType: modalType,
        messageTitle: modalTitle,
        messageContent: modalContent,
        messageImage: avatar
    };
    log('调用 showAppPush，参数:', 'debug', params);
    showAppPush(params);
}

function connectWebSocket() {
    return new Promise((resolve, reject) => {
        log('connectWebSocket: 开始执行。', 'debug');

        if (!currentUserId || !currentUserToken) {
            const errMsg = '用户ID和令牌是连接所必需的。';
            log(errMsg, 'error');
            return reject(new Error(errMsg));
        }

        if (stompClient && stompClient.connected) {
            log('connectWebSocket: STOMP 客户端已连接，无需重复连接。', 'info');
            return resolve('STOMP 已连接。');
        }
        if (socketTask && (socketTask.readyState === 0 || socketTask.readyState === 1) ) { // CONNECTING or OPEN
             log('connectWebSocket: 底层 uni SocketTask 存在且正在连接或已打开，可能正在等待 STOMP 连接。', 'warn');
             // 这种情况可能是上一次STOMP连接失败但底层socket未完全关闭，或者正在重连中。
             // 通常 handleDisconnect 会清理，但为保险起见，也清理一次。
        }
        
        log(`connectWebSocket: 准备清理旧连接（如果存在）。 用户ID: ${currentUserId}`, 'info');
        // 清理旧的连接（如果存在）
        if (socketTask) {
            try {
                log('connectWebSocket: 正在关闭旧的 socketTask...', 'debug');
                socketTask.close({
                    success: () => log('connectWebSocket: 旧的 uni SocketTask 已成功关闭。', 'info'),
                    fail: (err) => log('connectWebSocket: 关闭旧的 uni SocketTask 失败: ' + err.errMsg, 'warn')
                });
            } catch (e) {
                log('connectWebSocket: 清理旧 SocketTask 实例时出错: ' + e.message, 'warn');
            }
            socketTask = null;
        }
        if (stompClient) {
             try {
                if (stompClient.disconnect && typeof stompClient.disconnect === 'function') {
                   log('connectWebSocket: 正在断开旧的 stompClient...', 'debug');
                   stompClient.disconnect(() => log('connectWebSocket: 旧的 stompClient断开回调执行。', 'info'), {});
                }
            } catch (e) {
                log('connectWebSocket: 清理旧 stompClient 时出错: ' + e.message, 'warn');
            }
            stompClient = null;
        }
        
        log(`connectWebSocket: 尝试以用户 ${currentUserId} 连接到 ${WS_BASE_URL} (使用 uni.connectSocket)...`, 'info');
        socketTask = uni.connectSocket({
            url: WS_BASE_URL,
            success: () => log('connectWebSocket: uni.connectSocket API 调用成功发起。', 'info'),
            fail: (err) => {
                log('connectWebSocket: uni.connectSocket API 调用失败: ' + err.errMsg, 'error');
                handleDisconnect(true);
                reject(err);
            }
        });
        log('connectWebSocket: SocketTask 实例已创建。', 'debug', socketTask);

        const wsAdapter = {
            send: (data) => {
                log('wsAdapter.send: 准备发送STOMP数据。', 'debug');
                if (socketTask) {
                    socketTask.send({ data: data,
                        success: () => log('wsAdapter.send: uni SocketTask 发送数据成功。', 'debug'),
                        fail: (err) => log('wsAdapter.send: uni SocketTask 发送数据失败: ' + err.errMsg, 'error')
                    });
                } else { log('wsAdapter.send: SocketTask 不存在，无法发送 STOMP 数据。', 'error'); }
            },
            close: () => {
                log('wsAdapter.close: 请求关闭 uni SocketTask。', 'debug');
                if (socketTask) { socketTask.close({}); }
            },
            onmessage: null, onopen: null, onclose: null, onerror: null, url: WS_BASE_URL,
        };
        log('connectWebSocket: wsAdapter 已创建。', 'debug');

        try {
            stompClient = Stomp.over(wsAdapter);
            log('connectWebSocket: Stomp.over(wsAdapter) 成功，stompClient已创建。', 'debug', stompClient);
        } catch (e) {
            log(`connectWebSocket: Stomp.over(wsAdapter) 失败: ${e.message}.`, 'error');
            if (socketTask && socketTask.close) socketTask.close({});
            socketTask = null;
            return reject(new Error(`Stomp.over(wsAdapter) 失败: ${e.message}`));
        }
        
        stompClient.debug = (str) => { log('[STOMP DEBUG] ' + str, 'debug'); };

        socketTask.onOpen(() => {
            log('socketTask.onOpen: 底层 WebSocket 连接已建立。', 'success');
            if (wsAdapter.onopen) {
                log('socketTask.onOpen: 调用 wsAdapter.onopen() 通知Stomp.js。', 'debug');
                wsAdapter.onopen(); // Stomp.js应已设置此回调
            }

            const connectHeaders = { 'Authorization': 'Bearer ' + currentUserToken };
			console.log("connectHeaders",connectHeaders);
            log('socketTask.onOpen: 准备发起 STOMP 连接，头部:', 'debug', connectHeaders);

            stompClient.connect(
                connectHeaders,
                (frame) => {
                    log('stompClient.connect success: STOMP 已连接。 Frame:', 'success', frame ? frame.toString() : 'No frame');
                    reconnectAttempts = 0;
                    const userNotificationQueue = `/user/queue/notifications`;
                    log(`stompClient.connect success: 准备订阅到 ${userNotificationQueue}`, 'debug');
                    stompClient.subscribe(userNotificationQueue, (message) => {
                        log('stompClient.subscribe callback: 收到原始STOMP消息。 Body:', 'info', message.body);
                        try {
                            const notificationData = JSON.parse(message.body);
                            log('stompClient.subscribe callback: 解析后的JSON:', 'info', notificationData);
                            handleNotificationDisplay(notificationData);
                            uni.$emit('onNotificationReceived', notificationData);
                        } catch (e) {
                            log('stompClient.subscribe callback: 处理接收到的消息时出错: ' + e.message + '. Body: ' + message.body, 'error');
                            handleNotificationDisplay({
                                notificationType: "消息错误",
                                contentPreview: "收到一条无法正确解析的消息。",
                                originalMessageBody: message.body 
                            });
                        }
                    }, { id: `stomp-sub-user-${currentUserId}` });
                    log(`stompClient.connect success: 成功订阅到 STOMP 目标: ${userNotificationQueue}`, 'success');
                    resolve('STOMP 已连接。');
                },
                (error) => { // STOMP 连接错误回调
                    let errorMessage = 'STOMP 连接失败';
                    if (typeof error === 'string') errorMessage = error;
                    else if (error && error.headers && error.headers.message) errorMessage = error.headers.message;
                    else if (error && error.body) errorMessage = error.body;
                    else if (error && error.message) errorMessage = error.message;
                    log('stompClient.connect error: STOMP 连接错误详情: ' + errorMessage, 'error', error);
                    
                    if (socketTask && socketTask.close) socketTask.close({});
                    socketTask = null;
                    handleDisconnect(true); // 尝试重连
                    reject(error instanceof Error ? error : new Error(errorMessage)); // 确保reject一个Error对象
                }
            );
        });

        socketTask.onMessage((res) => {
            // log('socketTask.onMessage: 收到原始WebSocket数据。', 'debug', res.data);
            if (wsAdapter.onmessage) {
                wsAdapter.onmessage({ data: res.data });
            } else {
                log('socketTask.onMessage: wsAdapter.onmessage 未设置，Stomp.js 可能未正确初始化。', 'warn');
            }
        });

        socketTask.onClose((res) => {
            log(`socketTask.onClose: uni SocketTask 连接已关闭。代码: ${res.code}, 原因: ${res.reason || 'N/A'}`, 'info', res);
            if (wsAdapter.onclose) {
                log('socketTask.onClose: 调用 wsAdapter.onclose() 通知Stomp.js。', 'debug');
                wsAdapter.onclose(res);
            }
            socketTask = null; 
            handleDisconnect(true); // 尝试重连，除非是用户主动断开 (由 currentUserToken 判断)
        });

        socketTask.onError((err) => {
            log('socketTask.onError: WebSocket 连接错误: ' + err.errMsg, 'error', err);
            if (wsAdapter.onerror) {
                log('socketTask.onError: 调用 wsAdapter.onerror() 通知Stomp.js。', 'debug');
                wsAdapter.onerror(err);
            }
            if (socketTask && socketTask.close) socketTask.close({});
            socketTask = null;
            handleDisconnect(true);
        });
    });
}

function handleDisconnect(shouldReconnect = false) {
    log(`handleDisconnect: 开始执行。shouldReconnect: ${shouldReconnect}`, 'debug');
    const wasStompConnected = stompClient && stompClient.connected;

    if (stompClient) {
        log('handleDisconnect: 尝试断开 stompClient...', 'debug');
        try {
            stompClient.disconnect(() => {
                 log('handleDisconnect: STOMP 主动断开回调执行。', 'info');
            }, {});
        } catch (e) {
             log('handleDisconnect: STOMP 主动断开时出错: ' + e.message, 'warn');
        }
        // stompClient = null; // 不在这里设为null，让重连逻辑或 connectWebSocket 开头来处理
    }

    if (socketTask) {
        log('handleDisconnect: 尝试关闭 socketTask...', 'debug');
        try {
            if (socketTask.readyState === 0 || socketTask.readyState === 1) { // CONNECTING or OPEN
                socketTask.close({
                    success: () => log('handleDisconnect: uni SocketTask 在 handleDisconnect 中关闭成功。', 'info'),
                    fail: (err) => log('handleDisconnect: uni SocketTask 在 handleDisconnect 中关闭失败: ' + err.errMsg, 'warn')
                });
            }
        } catch (e) {
            log('handleDisconnect: 关闭 uni SocketTask 时出错: ' + e.message, 'warn');
        }
        // socketTask = null; // socketTask.onClose 中会设为 null
    }
    
    if (wasStompConnected) {
        log('handleDisconnect: STOMP 连接先前已建立，现已断开或尝试断开。', 'info');
        // store.commit('im/SET_CONNECTED', false); // Vuex状态管理 (如果使用)
    }

    if (shouldReconnect && currentUserId && currentUserToken) {
        if (reconnectAttempts < MAX_RECONNECT_ATTEMPTS) {
            reconnectAttempts++;
            log(`handleDisconnect: 准备在 ${RECONNECT_DELAY / 1000}秒后尝试重新连接... (尝试次数 ${reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`, 'info');
            setTimeout(() => {
                log(`handleDisconnect: 执行重连尝试 ${reconnectAttempts}...`, 'info');
                connectWebSocket().catch(err => {
                    log(`handleDisconnect: 重连尝试 ${reconnectAttempts} 最终失败。错误: ${err && err.message ? err.message : JSON.stringify(err)}`, 'error');
                });
            }, RECONNECT_DELAY);
        } else {
            log('handleDisconnect: 已达到最大重连尝试次数。将不会自动重试。请检查网络或手动重连。', 'error');
            reconnectAttempts = 0; 
        }
    } else {
        reconnectAttempts = 0; 
        if (!currentUserId || !currentUserToken) {
            log('handleDisconnect: 不满足重连条件 (缺少 userId 或 token)，不尝试重连。', 'info');
        } else if (!shouldReconnect) {
            log('handleDisconnect: 不应重连 (例如用户主动断开)。', 'info');
        }
        stompClient = null; // 清理，因为不会自动重连了
    }
}

export default {
    connect: (userId, token) => {
        log(`外部调用 connect: UserID ${userId}`, 'info');
        if (!userId || !token) {
            const errMsg = '连接失败：userId 或 token 不能为空。';
            log(errMsg, 'error');
            return Promise.reject(new Error(errMsg));
        }
        currentUserId = userId;
        currentUserToken = token;
        reconnectAttempts = 0; // 每次新的外部连接请求都重置尝试次数
        return connectWebSocket();
    },

    disconnect: () => {
        log('外部调用 disconnect: 请求主动断开连接...', 'info');
        currentUserToken = null; // 清除token，将阻止后续自动重连
        reconnectAttempts = MAX_RECONNECT_ATTEMPTS; // 设为最大值，阻止当前重连序列
        handleDisconnect(false); // false 表示不应自动重连
    },

    isConnected: () => {
        const connected = !!(stompClient && stompClient.connected && socketTask && socketTask.readyState === 1);
        // log(`isConnected: STOMP connected: ${stompClient && stompClient.connected}, SocketTask readyState: ${socketTask ? socketTask.readyState : 'null'} -> ${connected}`, 'debug');
        return connected;
    }
};